package com.esayread.utils

import android.content.Context
import android.os.Environment
import android.util.Log
import com.esayread.data.Book
import com.esayread.data.BookFormat
import com.esayread.utils.FileFormatConfig
import com.esayread.utils.CoverExtractor
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.File
import java.text.SimpleDateFormat
import java.util.*

/**
 * 文件扫描器，用于扫描手机中支持的电子书格式文件
 */
class FileScanner(private val context: Context) {
    
    private val bookManager = BookManager(context)
    private val coverExtractor = CoverExtractor(context)
    private val pathManager = BookPathManager(context)
    
    companion object {
        private const val TAG = "FileScanner"
        // 扫描深度限制，避免过深的目录遍历
        private const val MAX_SCAN_DEPTH = 30
    }
    
    /**
     * 扫描手机中所有支持格式的电子书文件
     */
    suspend fun scanAllBooks(): List<Book> = withContext(Dispatchers.IO) {
        val allBooks = mutableListOf<Book>()
        Log.d("FileScanner", "Starting book scan...")
        
        try {
            // 扫描外部存储根目录（全目录递归扫描）
            val externalStorage = Environment.getExternalStorageDirectory()
            Log.d("FileScanner", "External storage: ${externalStorage.absolutePath}, exists: ${externalStorage.exists()}, canRead: ${externalStorage.canRead()}")
            if (externalStorage.exists() && externalStorage.canRead()) {
                Log.d("FileScanner", "开始递归扫描整个外部存储目录...")
                scanDirectory(externalStorage, allBooks, MAX_SCAN_DEPTH)
            }
            
            // 扫描应用私有目录
            val privateDir = context.getExternalFilesDir(null)
            Log.d("FileScanner", "Private dir: ${privateDir?.absolutePath}, exists: ${privateDir?.exists()}")
            privateDir?.let { scanDirectory(it, allBooks, MAX_SCAN_DEPTH) }
            
        } catch (e: Exception) {
            Log.e("FileScanner", "Error during book scan", e)
            e.printStackTrace()
        }
        
        val uniqueBooks = allBooks.distinctBy { it.filePath } // 去重
        Log.d("FileScanner", "Scan completed. Found ${allBooks.size} total files, ${uniqueBooks.size} unique books")
        
        // 过滤掉已存在的书籍
        val newBooks = bookManager.filterNewBooks(uniqueBooks)
        Log.d("FileScanner", "过滤后剩余 ${newBooks.size} 本新书籍")
        
        newBooks
    }
    
    /**
     * 扫描手机中所有支持格式的电子书文件（懒加载版本）
     * @param onBookFound 每找到一本书时的回调函数
     * @param onScanComplete 扫描完成时的回调函数
     */
    suspend fun scanAllBooksLazy(
        onBookFound: (Book) -> Unit,
        onScanComplete: (List<Book>) -> Unit
    ) = withContext(Dispatchers.IO) {
        val allBooks = mutableListOf<Book>()
        Log.d("FileScanner", "=== 开始懒加载扫描所有书籍 ===")
        Log.d("FileScanner", "当前线程: ${Thread.currentThread().name}")
        Log.d("FileScanner", "扫描深度限制: $MAX_SCAN_DEPTH")
        
        try {
            // 扫描外部存储根目录（全目录递归扫描）
            val externalStorage = Environment.getExternalStorageDirectory()
            Log.d("FileScanner", "External storage: ${externalStorage.absolutePath}, exists: ${externalStorage.exists()}, canRead: ${externalStorage.canRead()}")
            if (externalStorage.exists() && externalStorage.canRead()) {
                Log.d("FileScanner", "开始递归扫描整个外部存储目录...")
                scanDirectoryLazy(externalStorage, allBooks, MAX_SCAN_DEPTH, onBookFound = onBookFound)
            }
            
            // 扫描应用私有目录
            val privateDir = context.getExternalFilesDir(null)
            Log.d("FileScanner", "Private dir: ${privateDir?.absolutePath}, exists: ${privateDir?.exists()}")
            privateDir?.let { scanDirectoryLazy(it, allBooks, MAX_SCAN_DEPTH, onBookFound = onBookFound) }
            
            // 扫描常见的文档目录
            val commonDirs = listOf(
                File("/storage/emulated/0/Documents"),
                File("/storage/emulated/0/Download"),
                File("/storage/emulated/0/Books"),
                File("/sdcard/Documents"),
                File("/sdcard/Download"),
                File("/sdcard/Books")
            )
            
            for (dir in commonDirs) {
                Log.d("FileScanner", "检查常见目录: ${dir.absolutePath}, 存在: ${dir.exists()}, 可读: ${dir.canRead()}")
                if (dir.exists() && dir.canRead()) {
                    Log.d("FileScanner", "扫描常见目录: ${dir.absolutePath}")
                    scanDirectoryLazy(dir, allBooks, MAX_SCAN_DEPTH, onBookFound = onBookFound)
                }
            }
            
        } catch (e: Exception) {
            Log.e("FileScanner", "Error during lazy book scan", e)
            e.printStackTrace()
        }
        
        val uniqueBooks = allBooks.distinctBy { it.filePath } // 去重
        Log.d("FileScanner", "=== 扫描完成 ===")
        Log.d("FileScanner", "总共找到 ${allBooks.size} 个文件，${uniqueBooks.size} 本唯一书籍")
        Log.d("FileScanner", "书籍列表: ${uniqueBooks.map { "${it.title} (${it.format})" }}")
        
        // 过滤掉已存在的书籍
        val newBooks = bookManager.filterNewBooks(uniqueBooks)
        Log.d("FileScanner", "过滤后剩余 ${newBooks.size} 本新书籍")
        
        onScanComplete(newBooks)
    }
    
    /**
     * 递归扫描目录
     */
    private suspend fun scanDirectory(directory: File, books: MutableList<Book>, maxDepth: Int = MAX_SCAN_DEPTH, currentDepth: Int = 0) {
        if (currentDepth >= maxDepth || !directory.exists() || !directory.canRead()) {
            Log.d("FileScanner", "达到最大扫描深度或无法访问目录 ${directory.absolutePath}: depth=$currentDepth, exists=${directory.exists()}, canRead=${directory.canRead()}")
            return
        }
        
        Log.d("FileScanner", "开始扫描目录: ${directory.absolutePath} (深度: $currentDepth)")
        Log.d("FileScanner", "目录状态 - 存在: ${directory.exists()}, 可读: ${directory.canRead()}, 是目录: ${directory.isDirectory}")
        
        try {
            val files = directory.listFiles()
            if (files == null) {
                Log.w("FileScanner", "无法列出目录内容: ${directory.absolutePath}")
                return
            }
            
            Log.d("FileScanner", "目录 ${directory.name} 包含 ${files.size} 个项目")
            
            files.forEach { file ->
                Log.d("FileScanner", "检查项目: ${file.name} (是目录: ${file.isDirectory}, 是文件: ${file.isFile})")
                
                when {
                    file.isDirectory -> {
                        Log.d("FileScanner", "递归扫描子目录: ${file.name}")
                        scanDirectory(file, books, maxDepth, currentDepth + 1)
                    }
                    file.isFile -> {
                        Log.d("FileScanner", "检查文件: ${file.name}, 大小: ${file.length()} bytes")
                        if (isSupportedFile(file)) {
                            Log.d("FileScanner", "✓ 找到支持的电子书文件: ${file.absolutePath}")
                            // 检查该路径是否已在书架中
                            if (pathManager.isPathRecorded(file.absolutePath)) {
                                Log.d("FileScanner", "✗ 书籍已在书架中，跳过: ${file.absolutePath}")
                            } else {
                                val book = createBookFromFile(file)
                                books.add(book)
                                Log.d("FileScanner", "✓ 成功创建书籍对象: ${book.title}")
                            }
                        } else {
                            Log.d("FileScanner", "✗ 不支持的文件格式: ${file.name}")
                        }
                    }
                }
            }
        } catch (e: SecurityException) {
            Log.e("FileScanner", "权限不足，无法访问目录: ${directory.absolutePath}", e)
            e.printStackTrace()
        } catch (e: Exception) {
            Log.e("FileScanner", "扫描目录时出错: ${directory.absolutePath}", e)
            e.printStackTrace()
        }
    }
    
    /**
     * 递归扫描目录（懒加载版本）
     */
    private suspend fun scanDirectoryLazy(
        directory: File, 
        books: MutableList<Book>, 
        maxDepth: Int = MAX_SCAN_DEPTH, 
        currentDepth: Int = 0,
        onBookFound: (Book) -> Unit
    ) {
        if (currentDepth >= maxDepth || !directory.exists() || !directory.canRead()) {
            Log.d("FileScanner", "达到最大扫描深度或无法访问目录 ${directory.absolutePath}: depth=$currentDepth, exists=${directory.exists()}, canRead=${directory.canRead()}")
            return
        }
        
        Log.d("FileScanner", "开始懒加载扫描目录: ${directory.absolutePath} (深度: $currentDepth)")
        Log.d("FileScanner", "目录状态 - 存在: ${directory.exists()}, 可读: ${directory.canRead()}, 是目录: ${directory.isDirectory}")
        
        try {
            val files = directory.listFiles()
            if (files == null) {
                Log.w("FileScanner", "无法列出目录内容: ${directory.absolutePath}")
                return
            }
            
            Log.d("FileScanner", "目录 ${directory.name} 包含 ${files.size} 个项目")
            
            files.forEach { file ->
                Log.d("FileScanner", "检查项目: ${file.name} (是目录: ${file.isDirectory}, 是文件: ${file.isFile})")
                
                when {
                    file.isDirectory -> {
                        Log.d("FileScanner", "递归扫描子目录: ${file.name}")
                        scanDirectoryLazy(file, books, maxDepth, currentDepth + 1, onBookFound)
                    }
                    file.isFile -> {
                        Log.d("FileScanner", "检查文件: ${file.name}, 大小: ${file.length()} bytes")
                        if (isSupportedFile(file)) {
                            Log.d("FileScanner", "✓ 找到支持的电子书文件: ${file.absolutePath}")
                            val book = createBookFromFile(file)
                            books.add(book)
                            Log.d("FileScanner", "✓ 成功创建书籍对象: ${book.title}，立即回调")
                            // 实时回调找到的书籍
                            withContext(Dispatchers.Main) {
                                onBookFound(book)
                            }
                        } else {
                            Log.d("FileScanner", "✗ 不支持的文件格式: ${file.name}")
                        }
                    }
                }
            }
        } catch (e: SecurityException) {
            Log.e("FileScanner", "权限不足，无法访问目录: ${directory.absolutePath}", e)
            e.printStackTrace()
        } catch (e: Exception) {
            Log.e("FileScanner", "懒加载扫描目录时出错: ${directory.absolutePath}", e)
            e.printStackTrace()
        }
    }
    
    /**
     * 检查文件是否为支持的格式
     */
    private fun isSupportedFile(file: File): Boolean {
        val fileName = file.name
        val isSupported = FileFormatConfig.isSupportedFile(fileName)
        val hasSize = file.length() > 0
        val result = isSupported && hasSize
        Log.d("FileScanner", "检查文件: $fileName, 格式支持: $isSupported, 有内容: $hasSize, 最终结果: $result")
        return result
    }
    
    /**
     * 从文件创建Book对象
     */
    private suspend fun createBookFromFile(file: File): Book {
        val bookId = file.absolutePath.hashCode().toString()
        val format = getBookFormat(file.extension)
        
        val coverPath = try {
            coverExtractor.extractCover(file.absolutePath, format, bookId)
        } catch (e: Exception) {
            Log.w(TAG, "Failed to extract cover for ${file.name}", e)
            null
        }
        
        return Book(
            id = bookId,
            title = getFileNameWithoutExtension(file.name),
            author = "未知作者",
            coverPath = coverPath,
            filePath = file.absolutePath,
            fileSize = file.length(),
            format = format,
            addTime = file.lastModified(),
            categories = emptyList(),
            description = null
        )
    }
    
    /**
     * 获取不带扩展名的文件名
     */
    private fun getFileNameWithoutExtension(fileName: String): String {
        val lastDotIndex = fileName.lastIndexOf('.')
        return if (lastDotIndex > 0) {
            fileName.substring(0, lastDotIndex)
        } else {
            fileName
        }
    }
    
    /**
     * 根据文件扩展名获取BookFormat
     */
    private fun getBookFormat(extension: String): BookFormat {
        return FileFormatConfig.getBookFormat(extension)
    }
    
    /**
     * 获取文件大小的可读格式
     */
    fun getReadableFileSize(size: Long): String {
        val units = arrayOf("B", "KB", "MB", "GB")
        var fileSize = size.toDouble()
        var unitIndex = 0
        
        while (fileSize >= 1024 && unitIndex < units.size - 1) {
            fileSize /= 1024
            unitIndex++
        }
        
        return String.format("%.1f %s", fileSize, units[unitIndex])
    }
}